﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.IO;
using System.Diagnostics;
using System.Threading.Tasks;

namespace AthCommander.Model
{
    public class DirectoryView : BindingList<FileView>
    {
        private bool _suspend;
        private AsyncOperation _operation;
        public FileSystemWatcher Watcher;

        #region Constructors

        public DirectoryView(string path)
        {
            _operation = AsyncOperationManager.CreateOperation(null);

            Fill(path);

            Watcher = new FileSystemWatcher(path);
            Watcher.EnableRaisingEvents = true;

            Watcher.NotifyFilter = NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.LastAccess;
            Watcher.Changed += new FileSystemEventHandler(FileSystem_Changed);
            Watcher.Created += new FileSystemEventHandler(FileSystem_Created);
            Watcher.Deleted += new FileSystemEventHandler(FileSystem_Deleted);
            Watcher.Renamed += new RenamedEventHandler(FileSystem_Renamed);
        }

        public DirectoryView()
            : this(Environment.GetFolderPath(Environment.SpecialFolder.Personal))
        {
        }

        #endregion

        #region FileView

        private FileView _directory;
        public FileView Directory
        {
            get
            {
                return _directory;
            }
        }

        #endregion

        #region PrivateHelpers

        private void Fill(string path)
        {
            _suspend = true;

            Clear();

            // Pobieranie info katalogu dla sciezki
            DirectoryInfo info = new DirectoryInfo(path);

            // Ustawienie obecnego katalogu
            _directory = new FileView(info);

            // Odczytanie katalogow i plikow dla lokalizacji
            foreach (FileSystemInfo dicrectory in info.GetDirectories())
            {
                this.Add(new FileView(dicrectory));
            }

            foreach (FileSystemInfo file in info.GetFiles())
            {
                this.Add(new FileView(file));
            }

            _suspend = false;

            ResetBindings();
        }

        private FileSystemInfo GetFileSystemInfo(string path)
        {
            FileSystemInfo fileInfo = new FileInfo(path);

            if ((fileInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
            {
                fileInfo = new DirectoryInfo(path);
            }

            return fileInfo;
        }

        #endregion

        #region Methods

        public void Activate(FileView fileView)
        {
            if (fileView.IsDirectory)
            {
                // Odswiez liste
                Fill(fileView.FullName);
                Watcher.Path = fileView.FullName;
            }
            else
            {
                Process process = new Process();
                process.StartInfo.FileName = fileView.FullName;
                process.StartInfo.Verb = "Open";
                process.Start();
            }
        }

        public void Activate(string path)
        {
            // Odswiez liste
            Fill(path);
            Watcher.Path = path;
        }

        public void Up()
        {
            DirectoryInfo di = new DirectoryInfo(_directory.FullName);
            DirectoryInfo parent = di.Parent;

            if (null != parent)
            {
                Fill(parent.FullName);
            }
        }

        public FileView Find(string name)
        {
            FileView item = null;

            foreach (FileView fileView in this.Items)
            {
                if (fileView.Name == name)
                {
                    item = fileView;
                    break;
                }
            }

            return item;
        }

        #endregion

        #region EventsHandlers

        void FileSystem_Changed(object sender, FileSystemEventArgs e)
        {
            FileView fileView = Find(e.Name);

            if (null != fileView)
            {
                fileView.Update();
                this.ResetItem(this.IndexOf(fileView));
            }
        }

        void FileSystem_Created(object sender, FileSystemEventArgs e)
        {
            this.Add(new FileView(GetFileSystemInfo(e.FullPath)));
            Fill(this._directory.FullName);

        }

        void FileSystem_Deleted(object sender, FileSystemEventArgs e)
        {
            FileView fileView = this.Find(e.Name);

            if (null != fileView)
            {
                this.Remove(fileView);
            }
        }

        void FileSystem_Renamed(object sender, RenamedEventArgs e)
        {
            FileView fileView = Find(e.OldName);

            if (null != fileView)
            {
                fileView.Update(GetFileSystemInfo(e.FullPath));
                this.ResetItem(this.IndexOf(fileView));
            }
        }

        #endregion

    }
}
